import crypto from 'crypto';
import axios, { AxiosResponse } from 'axios';
import fs from 'fs';
import { execSync } from 'child_process';

/**
 * 订单数据接口
 */
interface OrderData {
  amount: number;
  description: string;
  outTradeNo: string;
  timeExpire?: string;
  openid: string;
}

/**
 * 退款数据接口
 */
interface RefundData {
  transactionId?: string;
  outTradeNo?: string;
  outRefundNo: string;
  reason: string;
  refundAmount: number;
  totalAmount: number;
  notifyUrl?: string;
}

/**
 * 微信支付响应接口
 */
interface WechatPayResponse {
  success: boolean;
  prepayId?: string;
  refundId?: string;
  status?: string;
  amount?: any;
  data?: any;
  error?: string;
  mockMode?: boolean;
}

/**
 * 支付参数接口
 */
interface PaymentParams {
  timeStamp: string;
  nonceStr: string;
  package: string;
  signType: string;
  paySign: string;
  mockMode?: boolean;
  error?: string;
}

/**
 * 微信支付服务类
 */
export class WechatPayService {
  private appId: string;
  private mchId: string;
  private apiV3Key: string;
  private certPath: string;
  private keyPath: string;
  private notifyUrl: string;
  private mockMode: boolean;
  private baseUrl: string;

  constructor() {
    this.appId = process.env.WECHAT_APPID || '';
    this.mchId = process.env.WECHAT_PAY_MCHID || '';
    this.apiV3Key = process.env.WECHAT_PAY_APIV3_KEY || '';
    this.certPath = process.env.WECHAT_PAY_CERT_PATH || '';
    this.keyPath = process.env.WECHAT_PAY_KEY_PATH || '';
    this.notifyUrl = process.env.WECHAT_PAY_NOTIFY_URL || '';
    this.mockMode = process.env.PAYMENT_MOCK_MODE === 'true';
    
    // 微信支付API基础URL
    this.baseUrl = 'https://api.mch.weixin.qq.com';
    
    if (this.mockMode) {
      console.log('🔧 微信支付运行在模拟模式');
    }
  }

  /**
   * 生成签名
   */
  private generateSignature(method: string, url: string, timestamp: number, nonce: string, body: string = ''): string {
    const message = `${method}\n${url}\n${timestamp}\n${nonce}\n${body}\n`;
    
    try {
      const privateKey = fs.readFileSync(this.keyPath, 'utf8');
      const sign = crypto.createSign('RSA-SHA256');
      sign.update(message);
      return sign.sign(privateKey, 'base64');
    } catch (error) {
      console.error('生成签名失败:', error);
      throw new Error('签名生成失败');
    }
  }

  /**
   * 获取授权头
   */
  private getAuthorizationHeader(method: string, url: string, body: string = ''): string {
    const timestamp = Math.floor(Date.now() / 1000);
    const nonce = crypto.randomBytes(16).toString('hex');
    const signature = this.generateSignature(method, url, timestamp, nonce, body);
    
    return `WECHATPAY2-SHA256-RSA2048 mchid="${this.mchId}",nonce_str="${nonce}",timestamp="${timestamp}",serial_no="${this.getCertSerialNo()}",signature="${signature}"`;
  }

  /**
   * 获取证书序列号
   */
  private getCertSerialNo(): string {
    try {
      const cert = fs.readFileSync(this.certPath, 'utf8');
      
      // 使用Node.js的crypto模块解析X.509证书
      const x509 = new crypto.X509Certificate(cert);
      
      // 获取证书序列号（十六进制格式，需要转换为大写）
      const serialNumber = x509.serialNumber;
      
      console.log('证书序列号:', serialNumber);
      return serialNumber;
      
    } catch (error) {
      console.error('获取证书序列号失败:', error);
      
      // 如果新方法失败，尝试使用openssl命令行工具（备用方案）
      try {
        const result = execSync(`openssl x509 -in ${this.certPath} -noout -serial`, { encoding: 'utf8' });
        const match = result.match(/serial=([A-F0-9]+)/i);
        if (match) {
          console.log('通过openssl获取证书序列号:', match[1]);
          return match[1].toUpperCase();
        }
      } catch (opensslError) {
        console.error('openssl备用方案也失败:', opensslError);
      }
      
      return '';
    }
  }

  /**
   * 小程序下单
   */
  async createOrder(orderData: OrderData): Promise<WechatPayResponse> {
    // 验证必需参数
    if (!orderData.amount || orderData.amount <= 0) {
      return {
        success: false,
        error: '支付金额不能为空或小于等于0'
      };
    }

    if (!orderData.description) {
      return {
        success: false,
        error: '订单描述不能为空'
      };
    }

    if (!orderData.outTradeNo) {
      return {
        success: false,
        error: '商户订单号不能为空'
      };
    }

    // 模拟模式
    if (this.mockMode) {
      console.log('🎭 模拟支付下单:', orderData);
      const mockPrepayId = `mock_prepay_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;

      return {
        success: true,
        prepayId: mockPrepayId
      };
    }

    // 真实支付模式
    const url = '/v3/pay/transactions/jsapi';
    const fullUrl = this.baseUrl + url;
    
    const requestBody = {
      appid: this.appId,
      mchid: this.mchId,
      description: orderData.description,
      out_trade_no: orderData.outTradeNo,
      time_expire: orderData.timeExpire,
      notify_url: this.notifyUrl,
      amount: {
        total: Math.round(orderData.amount * 100), // 转换为分
        currency: 'CNY'
      },
      payer: {
        openid: orderData.openid
      }
    };

    const body = JSON.stringify(requestBody);
    
    try {
      const response: AxiosResponse = await axios.post(fullUrl, requestBody, {
        headers: {
          'Content-Type': 'application/json',
          'Accept': 'application/json',
          'Authorization': this.getAuthorizationHeader('POST', url, body)
        }
      });

      return {
        success: true,
        prepayId: response.data.prepay_id
      };
    } catch (error: any) {
      console.error('微信支付下单失败:', error.response?.data || error.message);
      return {
        success: false,
        error: error.response?.data?.message || '下单失败'
      };
    }
  }

  /**
   * 查询订单
   */
  async queryOrder(outTradeNo: string): Promise<WechatPayResponse> {
    const url = `/v3/pay/transactions/out-trade-no/${outTradeNo}?mchid=${this.mchId}`;
    const fullUrl = this.baseUrl + url;
    
    try {
      const response: AxiosResponse = await axios.get(fullUrl, {
        headers: {
          'Accept': 'application/json',
          'Authorization': this.getAuthorizationHeader('GET', url)
        }
      });

      return {
        success: true,
        data: response.data
      };
    } catch (error: any) {
      console.error('查询订单失败:', error.response?.data || error.message);
      return {
        success: false,
        error: error.response?.data?.message || '查询失败'
      };
    }
  }

  /**
   * 生成小程序支付参数
   */
  generatePaymentParams(prepayId: string): PaymentParams {
    const timestamp = Math.floor(Date.now() / 1000).toString();
    const nonceStr = crypto.randomBytes(16).toString('hex');
    const packageStr = `prepay_id=${prepayId}`;
    
    // 模拟模式
    if (this.mockMode) {
      console.log('🎭 生成模拟支付参数');
      return {
        timeStamp: timestamp,
        nonceStr: nonceStr,
        package: packageStr,
        signType: 'RSA',
        paySign: 'mock_pay_sign_' + nonceStr,
        mockMode: true
      };
    }

    // 真实支付模式
    try {
      // 生成签名
      const message = `${this.appId}\n${timestamp}\n${nonceStr}\n${packageStr}\n`;
      const privateKey = fs.readFileSync(this.keyPath, 'utf8');
      const sign = crypto.createSign('RSA-SHA256');
      sign.update(message);
      const paySign = sign.sign(privateKey, 'base64');

      return {
        timeStamp: timestamp,
        nonceStr: nonceStr,
        package: packageStr,
        signType: 'RSA',
        paySign: paySign
      };
    } catch (error) {
      console.error('生成支付参数失败，可能是证书文件问题:', error);
      // 如果证书有问题，返回模拟参数
      return {
        timeStamp: timestamp,
        nonceStr: nonceStr,
        package: packageStr,
        signType: 'RSA',
        paySign: 'fallback_mock_sign_' + nonceStr,
        mockMode: true,
        error: '证书文件问题，使用模拟模式'
      };
    }
  }

  /**
   * 验证支付回调签名
   */
  verifyNotifySignature(headers: Record<string, string>, body: string): boolean {
    const timestamp = headers['wechatpay-timestamp'];
    const nonce = headers['wechatpay-nonce'];
    const signature = headers['wechatpay-signature'];
    const serial = headers['wechatpay-serial'];

    const message = `${timestamp}\n${nonce}\n${body}\n`;
    
    try {
      // 这里需要微信支付平台证书来验证，实际项目中需要下载并配置
      // 简化处理，实际使用时需要完善
      return true;
    } catch (error) {
      console.error('验证回调签名失败:', error);
      return false;
    }
  }

  /**
   * 解密回调数据
   */
  decryptNotifyData(encryptedData: { ciphertext: string; associated_data: string; nonce: string }): any {
    try {
      const { ciphertext, associated_data, nonce } = encryptedData;

      const decipher = crypto.createDecipheriv('aes-256-gcm', Buffer.from(this.apiV3Key), Buffer.from(nonce, 'base64'));
      decipher.setAAD(Buffer.from(associated_data, 'utf8'));
      
      let decrypted = decipher.update(ciphertext, 'base64', 'utf8');
      decrypted += decipher.final('utf8');

      return JSON.parse(decrypted);
    } catch (error) {
      console.error('解密回调数据失败:', error);
      throw new Error('解密失败');
    }
  }

  /**
   * 申请退款
   */
  async refund(refundData: RefundData): Promise<WechatPayResponse> {
    // 模拟模式
    if (this.mockMode) {
      console.log('🎭 模拟退款申请:', refundData);
      const mockRefundId = `mock_refund_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;

      return {
        success: true,
        refundId: mockRefundId,
        status: 'SUCCESS',
        mockMode: true
      };
    }

    // 真实退款模式
    const url = '/v3/refund/domestic/refunds';
    const fullUrl = this.baseUrl + url;

    const requestBody: any = {
      out_refund_no: refundData.outRefundNo,
      reason: refundData.reason,
      amount: {
        refund: Math.round(refundData.refundAmount * 100), // 转换为分
        total: Math.round(refundData.totalAmount * 100),   // 转换为分
        currency: 'CNY'
      }
    };

    // 优先使用微信支付订单号，其次使用商户订单号
    if (refundData.transactionId) {
      requestBody.transaction_id = refundData.transactionId;
    } else if (refundData.outTradeNo) {
      requestBody.out_trade_no = refundData.outTradeNo;
    } else {
      return {
        success: false,
        error: '必须提供微信支付订单号或商户订单号'
      };
    }

    // 如果提供了退款回调地址
    if (refundData.notifyUrl) {
      requestBody.notify_url = refundData.notifyUrl;
    }

    const body = JSON.stringify(requestBody);

    try {
      const response: AxiosResponse = await axios.post(fullUrl, requestBody, {
        headers: {
          'Content-Type': 'application/json',
          'Accept': 'application/json',
          'Authorization': this.getAuthorizationHeader('POST', url, body)
        }
      });

      return {
        success: true,
        refundId: response.data.refund_id,
        status: response.data.status,
        amount: response.data.amount
      };
    } catch (error: any) {
      console.error('微信支付退款失败:', error.response?.data || error.message);
      return {
        success: false,
        error: error.response?.data?.message || '退款申请失败'
      };
    }
  }

  /**
   * 查询退款
   */
  async queryRefund(outRefundNo: string): Promise<WechatPayResponse> {
    // 模拟模式
    if (this.mockMode) {
      console.log('🎭 模拟查询退款:', outRefundNo);
      return {
        success: true,
        status: 'SUCCESS',
        refundId: `mock_refund_${outRefundNo}`,
        mockMode: true
      };
    }

    // 真实查询模式
    const url = `/v3/refund/domestic/refunds/${outRefundNo}`;
    const fullUrl = this.baseUrl + url;

    try {
      const response: AxiosResponse = await axios.get(fullUrl, {
        headers: {
          'Accept': 'application/json',
          'Authorization': this.getAuthorizationHeader('GET', url)
        }
      });

      return {
        success: true,
        data: response.data
      };
    } catch (error: any) {
      console.error('查询退款失败:', error.response?.data || error.message);
      return {
        success: false,
        error: error.response?.data?.message || '查询退款失败'
      };
    }
  }

  /**
   * 验证退款回调签名
   */
  verifyRefundNotifySignature(headers: Record<string, string>, body: string): boolean {
    // 模拟模式直接返回true
    if (this.mockMode) {
      console.log('🎭 模拟退款回调签名验证通过');
      return true;
    }

    // 真实验证逻辑（与支付回调验证类似）
    return this.verifyNotifySignature(headers, body);
  }

  /**
   * 生成退款单号
   */
  generateRefundNumber(orderNumber: string): string {
    const timestamp = Date.now();
    const random = Math.random().toString(36).substr(2, 6);
    return `RF${orderNumber.replace('PK', '')}${timestamp}${random}`.toUpperCase();
  }
}

// 创建单例实例并导出
const wechatPayService = new WechatPayService();
export default wechatPayService;